package com.netease.ticket;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.Scanner;

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;

import com.netease.ocr.VerifyCodeUtil;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

/**
 * 登陆
 * @author bjyangfan
 *
 */
public class Login {
	
	private String Url12306 = "http://dynamic.12306.cn/otsweb";
	private String loginJsUrl = "http://dynamic.12306.cn/otsweb/dynamicJsAction.do?jsversion=";
	private String loginInitUrl = "http://dynamic.12306.cn/otsweb/loginAction.do?method=init";
	private String LoginUrl = "http://dynamic.12306.cn/otsweb/loginAction.do?method=login";
	
	private String yzmUrl = "http://dynamic.12306.cn/otsweb/passCodeNewAction.do?module=login&rand=sjrand";
	//private String yzmUrl = "http://dynamic.12306.cn/otsweb/passCodeAction.do?rand=sjrand";//该地址2013-9-11日后停用，使用上边的地址
	private String loginRandomNum = "http://dynamic.12306.cn/otsweb/loginAction.do?method=loginAysnSuggest";
	private String logoutUrl = "http://dynamic.12306.cn/otsweb/loginAction.do?method=logout";
	
	private String Cookie12306 = "12306cookie.txt";
	
	private String yzmFileName = "passCodeAction.tiff";
	
	public String jsFile = "12306.js";
	public String jsFileRaw = "12306raw.js";
	
	private NameValuePair jsResult = null;
	
	public HttpClient client;
	public String cookie = "";
	
	public Login()
	{
		client = new HttpClient();
		
		//设置代理服务器地址和端口     
		//client.getHostConfiguration().setProxy("86.62.98.98",3128);

		//生成1000-9999之间的随机数
		int rand10000 = (int)(Math.random() * 9000 + 1000);
		loginJsUrl += String.valueOf(rand10000) + "&method=loginJs";
	}
	
	/**
	 * 退出
	 * @throws Exception
	 */
	public void logout() throws Exception
	{
		HttpMethod method = new GetMethod(logoutUrl);
		Util.setReqHeader(method, Url12306,  cookie);
        client.executeMethod(method);
	}
	
	/**
	 * 获取验证码
	 * @return
	 * @throws Exception
	 */
	public String getyzm(String user) throws Exception
	{
		HttpMethod getYZMMethod = new GetMethod(yzmUrl);
		String yzm;
		//Scanner sc = new Scanner(System.in);

		Util.setReqHeader(getYZMMethod, loginInitUrl,  cookie);
		while(true){
	    	
	        client.executeMethod(getYZMMethod);
	        
	        //打印服务器返回的状态
		     System.out.println(getYZMMethod.getStatusLine());
				
		     File storeFile = new File(user + yzmFileName);
		     FileOutputStream output = new FileOutputStream(storeFile);
		     
		     //得到网络资源的字节数组,并写入文件 
		     output.write(getYZMMethod.getResponseBody());
		     output.close();
		     
		     yzm = VerifyCodeUtil.crackVerifyCode(user + yzmFileName);
		     System.out.print("识别出的初始验证码：" + yzm);
		     

		     yzm = Util.paseYzm(yzm);
		     System.out.println(",进一步处理后的验证码：" + yzm);
		     
		     if(yzm.length() != 4)continue;
		     else break;
		     
//		     yzm = sc.next();
//		     break;
		 }

	     return yzm;
	}
	
	/**
	 * 获取随机数
	 * @return
	 * @throws Exception
	 */
	public String getRand() throws Exception
	{
		HttpMethod postRanMethod = new PostMethod(loginRandomNum);
		String ran = "";
		postRanMethod.getDoAuthentication();
	    Util.setReqHeader(postRanMethod, loginInitUrl,  cookie);
	    postRanMethod.setRequestHeader("X-Requested-With","XMLHttpRequest");
	    
	    for (int i= 0; i < 10; i++){
		    client.executeMethod(postRanMethod);
		     
		    //打印服务器返回的状态
		    System.out.println(postRanMethod.getStatusLine());
		    //打印返回的信息
		    ran = postRanMethod.getResponseBodyAsString();
		    System.out.println(ran);
		     
		    //截取随机数,这里有时可能获取不到正确的结果
		    try{
		    	ran = ran.substring(ran.indexOf(':') +2, ran.indexOf(',')-1);
		    	break;
		    }catch(Exception ex){continue;}
	    }
	    
	    return ran;
	}
	
	/**
	 * 将cookie写入文件
	 * @param cookies
	 * @throws Exception
	 */
	private void writeCookie(String fileName, Cookie[] cookies) throws Exception
	{
		File storeFile = new File(fileName);
	    FileOutputStream output = new FileOutputStream(storeFile);
	    output.write(Util.cookie2String(cookies).getBytes());
	    output.close();
	}
	
	
	/**
	 * 登陆
	 * @param user 用户名
	 * @param pwd 密码
	 * @return HttpClient
	 * @throws Exception
	 */
	public HttpClient login(String user, String pwd) throws Exception
	{
		HttpMethod method;
        //[truncated] loginRand=71&refundLogin=N&refundFlag=Y&isClick=&form_tk=null&loginUser.user_name=yf198557&nameErrorFocus=&user.password=850507&passwordErrorFocus=&randCode=6UNA&randErrorFocus=&MzcyNjE1Nw%3D%3D=ZmFlMzUwNzYxMmJmYmYxMA%3D%3D&myv
        int code = 0;
        String html;
        PostMethod loginMethod = new PostMethod(LoginUrl);
        
        //读取cookie
        cookie = Util.readFile(user + Cookie12306, "UTF-8");
        
    	method = new GetMethod(loginInitUrl);
    	Util.setReqHeader(method, Url12306,  cookie);
    	
    	code = client.executeMethod(method);
    	
    	if(code != 200)
    	{
    		//删除cookie
			File cookieFile = new File(user + Cookie12306);
			if(cookieFile.exists())cookieFile.delete();
    		return null;
    	}
    	
    	//打印服务器返回的状态
	    System.out.println(method.getStatusLine());
	    
	    //打印返回的信息
	    String content = new String (method.getResponseBody(), "UTF-8");
	    //System.out.println(content);
	    
	    //如果已经登陆过就不重新登录 
	    if(content.indexOf("刷新验证码") <= 0)
	    {
	    	System.out.println("cookie可用， 无需登陆。");
	    	return client;
	    }
	    
    	Cookie[] cookies = client.getState().getCookies();
    	cookie = Util.cookie2String(cookies);
	    
    	method = new GetMethod(loginJsUrl);
    	Util.setReqHeader(method, loginInitUrl,  cookie);
    	
    	client.executeMethod(method);
    	html = method.getResponseBodyAsString();
    	html = html.replace("aj();", "");  	
    	jsResult = Util.getJsResult(user + jsFile, html);
    	
    	//保存原始文件
    	Util.writeFile(user + jsFileRaw, html);
    	
    	Util.setReqHeader(loginMethod, loginInitUrl,  cookie);
    	
    	 while(true){
    		 
    		 try{
	    		 NameValuePair[] param = { 
		   			 new NameValuePair("loginRand",getRand()),
	                 new NameValuePair("refundLogin","N"),
	                 new NameValuePair("refundFlag","Y"), 
	                 new NameValuePair("isClick", ""),
	                 new NameValuePair("loginUser.user_name",user),
	                 new NameValuePair("nameErrorFocus",""),
	                 new NameValuePair("user.password",pwd),
	                 new NameValuePair("passwordErrorFocus",""),
	                 new NameValuePair("randCode",getyzm(user)),
	                 new NameValuePair("randErrorFocus",""),
	                 jsResult,
		   			 new NameValuePair("myversion","undefined")
	    	   	 } ;
	    		 
		    	 loginMethod.setRequestBody(param);
		    	 code = client.executeMethod(loginMethod);
    		 }
    		 catch(Exception ex)
    		 {
    			 continue;
    		 }
	    	 
	    	 if(code != 200)Util.redirect(loginMethod, client, loginInitUrl, cookie);
		     
	    	 //打印服务器返回的状态
		     System.out.println(loginMethod.getStatusLine());
		     
		     html = new String(loginMethod.getResponseBody(), "UTF-8");
		     System.out.println(html);
		     if(html.length() > 100 && html.indexOf("单击刷新验证码") <= 0)break;
		     else System.out.println(html);
		    	 
    	 }
	     
    	 //打印返回的信息
	     System.out.println(html);
	     
	     cookies = client.getState().getCookies();
	     
	     writeCookie(user + Cookie12306, cookies);
	     
	     return client;
	}
}
